class WorkitemController < ApplicationController  

  before_filter :login_required   
  include HashModel
  
  
  def index
    list
    render :action => 'list'
  end

  # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
  verify :method => :post, :only => [ :destroy, :create, :update ],
         :redirect_to => { :action => :list }

  def list    
    
    # in order to support users in multipe roles, the work list gathering must happen
    # individually. There are five situations in which work need to be done. Depending on the
    # content of the five arrays, the worklist will be created.

    # TODO: assigning judges should be done automatically.
    @judgments = []
    @approvals = []
    @submissions = []
    @assign_judges = []  
    @no_work = false;
   
    if current_user.is_admin? or current_user.is_adminasst?
      conn = ActiveRecord::Base.connection()
      sql = " SELECT s.id as id,
                     c.name as cycle_name,
                     u.first_name as user_first_name,                    
                     u.last_name as user_last_name,
                     m.first_name as manager_first_name,                                        
                     m.last_name as manager_last_name,                                        
                     sites.name as site_name,
                     statuses.name as status_name
                FROM submissions s,
                     cycles c,
                     users u,
                     users m,
                     sites,
                     statuses
               WHERE s.cycle_id = c.id
                 AND s.user_id = u.id
                 AND s.manager_id = m.id
                 AND m.site_id = sites.id
                 AND s.status_id = statuses.id
                 AND statuses.name = 'Approved'"
        @assign_judges = conn.select_all(sql)
    end
    
    if current_user.is_manager?
      @approvals = Approval.find(:all, :conditions => ["manager_id = ? and complete = ?", current_user, false])     
    end
    
    if current_user.is_judge?
      @judgments = Judgment.find(:all, :conditions => ["judge_id = ? and complete = ?", current_user, false], :include => [{:submission => :cycle}])
    end
    
    if current_user.is_seeker?
      @submissions = Submission.find(:all, :conditions => ["user_id = ?", current_user])
    end
    
    if @judgments.empty? && @approvals.empty? && @submissions.empty? && @assign_judges.empty?
      @no_work = true
    end
    
  end

  def show
    @submission = Submission.find(params[:id]) 
    
    if @submission.data
      @submission_data = HashModel::Model.new(YAML::load(@submission.data))
    else    
      @submission_data = HashModel::Model.new({})
    end
  end 
  
  def print
    @submission = Submission.find(params[:id]) 
    
    if @submission.data
      @submission_data = HashModel::Model.new(YAML::load(@submission.data))
    else    
      @submission_data = HashModel::Model.new({})
    end
  end

  def new      
    @cycle = Cycle.find(params[:id])
                                        
    if not @cycle
      flash[:notice] = "The cycle you chose must have an error."   
      redirect_back_or_default(:controller => 'cycle', :action => 'list')
      return
    end
        
    @submission = Submission.new   
    @submission.cycle = @cycle  
    @submission.status = Status.find_or_create_by_name('In Progress')  
    @submission.manager = current_user.site.manager
    @submission.user = current_user
    if @submission.save!
      flash[:notice] = 'Application was successful'
      redirect_to :controller=> 'workitem', :action => 'list'
    end
  end

  def create
    @submission = Submission.new(params[:submission])
    if @submission.save
      flash[:notice] = 'Submission was successfully created.'
      redirect_to :action => 'list'
    else
      render :action => 'new'
    end
  end

  def edit      
      
    @submission = Submission.find(params[:id], :include => [:approvals])  
    @judgment = nil
    @approval = nil     
    
    @sites = Site.find(:all, :order => 'name', :include => 'manager');
                                   
    # TODO: move this exception logic to a before filter.
    # protect this from unauthorized edit
    if not ["In Progress", "Not Approved"].index(@submission.status.name)
      redirect_to :action => 'show', :id => @submission  
      return
    end 
    
    if current_user != @submission.user
      redirect_to :action =>'show', :id => @submission     
      return
    end
    
                            
    if @submission.data
      @submission_data = HashModel::Model.new(YAML::load(@submission.data))
    else    
      @submission_data = HashModel::Model.new({})
    end
                      
    # # if the user is a manager, then we need to make sure there is an approval object.
    # if current_user.is_manager? && @submission.approval == nil 
    #   @submission.approvals << Approval.create(:manager => Manager.find(current_user) );
    # elsif current_user.is_judge?
    #   @judgment = @submission.judgments.find_by_judge_id(current_user.id)
    # end    
    
  end 
  
  def update
    @submission = Submission.find(params[:id])
    submission_params = params[:submission] 
    submission_params[:total_cost] = calculate_total_cost(params[:submission_data])
    submission_params[:data] = YAML::dump(params[:submission_data])  
    
    # update the submission.
    if @submission.update_attributes(submission_params)  
      
      # if there is not a manager_id, then we need to make sure that the user fills it out.
      if @submission.manager == nil
        @submission.errors.add('Manager', 'is required. Please choose one at the bottom of the form.') 
        
        if @submission.data
          @submission_data = HashModel::Model.new(YAML::load(@submission.data))
        else    
          @submission_data = HashModel::Model.new({})
        end
        render :action => 'edit'
      else
        flash[:notice] = 'Application was successfully updated.' 
        
        if params[:commit] == "Print"
          redirect_to :action => 'print', :id => params[:id]
        else 
          redirect_to :action => 'list'
        end
      end
    else 
      
      # if there was an error saving then go back to edit.
      render :action => 'edit'
    end
  end
  
  def submit      
    @submission = Submission.find(params[:id], :include => [:approvals, :manager])  
    
    # TODO: move this exception logic to a before filter.
    # protect this from unauthorized edit
    if not ["In Progress", "Not Approved"].index(@submission.status.name)   
      flash[:notice] = "you can't do that."
      redirect_to :action => 'list'  
      return
    end 
     
    # protect this from unauthorized edit
    if current_user != @submission.user 
      flash[:notice] = "you can't do that, either"
      redirect_to :action =>'list'     
      return
    end
    
    # If the status is Not Approved, that means that we need to reset some of the existing approvals.
    if @submission.status.name == 'Not Approved'
      # reset all of the approvers complete flag.
      @submission.approvals.update_all("complete = 0")   
                          
      # notify the approvers that work is waiting for them.
      @submission.approvals.each { |approval|
        UserNotifier.deliver_waiting_approval(approval.manager)                                                                           
      }
    end
    
    @submission.status = Status.find_or_create_by_name("Awaiting Approval") 
    @submission.submitted_at = Time.now() 
    @submission.add_approval(@submission.manager)                  
    @submission.save    
    redirect_to :action => 'list'  
  end   
    
  def save_seeker_form
    @submission = Submission.find(params[:id])
    submission_params = params[:submission]     
    submission_params[:total_cost] = calculate_total_cost(params[:submission_data])
    submission_params[:data] = YAML::dump(params[:submission_data])

    if @submission.update_attributes(submission_params)
      render :text => "Application automatically saved on #{Time.now}"
    else
      render :text => 'Error saving draft!'
    end
  end
  
  def total_cost
    render :text => sprintf("$ %0.2f", calculate_total_cost(params[:submission_data])) 
  end 
  
  def calculate_total_cost(p)
    total_cost = 0
    p.each { |k,v|
      next if not v
      next if /\A\Z/.match(v.to_s)
      next if not /\Apaid/.match(k.to_s)

      if (m = /\A\$?\s*([+\-]?[\d\.]+)\Z/.match(v.to_s))   
        logger.debug "adding #{m[1]} to #{total_cost} (float: #{m[1].to_f})"
        total_cost = total_cost + m[1].to_f
      else
        logger.error "v is not a number #{v}"
        total_cost = -1
        break;
      end
    }
    total_cost
  end 
end
